package main

import (
	"bytes"
	"crypto/md5"
	"crypto/sha256"
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"strconv"
	"strings"
	"sync"
	"time"

	"github.com/gin-gonic/gin"
	"github.com/sirupsen/logrus"
)

// AuthConfig 认证配置
type AuthConfig struct {
	AppID             string // 应用ID
	AppKey            string // 应用密钥
	AppSecret         string // 应用密钥
	BaseURL           string // 基础URL
	BaseAuthURL       string // 统一登录跳转URL
	RedirectURI       string // 重定向URI
	LogoutCallbackURI string // 登出回调URI
}

// PingshuUserDTO 用户信息DTO
type PingshuUserDTO struct {
	UserID    string                      `json:"userId"`    // 用户ID
	Username  string                      `json:"username"`  // 用户名
	Mobile    string                      `json:"mobile"`    // 手机号
	IsRoot    int                         `json:"isRoot"`    // 是否是根用户，1是，0否
	Status    int                         `json:"status"`    // 用户状态，1正常，0禁用
	Positions []PingshuUserSubPositionDTO `json:"positions"` // 用户职位列表
}

// PingshuUserSubPositionDTO 用户职位信息DTO
type PingshuUserSubPositionDTO struct {
	DeptCode           string `json:"deptCode"`           // 部门编码
	DeptName           string `json:"deptName"`           // 部门名称
	ThirdDeptCode      string `json:"thirdDeptCode"`      // 三级部门编码
	ThirdDeptName      string `json:"thirdDeptName"`      // 三级部门名称
	Department         string `json:"department"`         // 部门
	IsRoot             int    `json:"isRoot"`             // 是否是根部门，1是，0否
	PostNames          string `json:"postNames"`          // 职位名称
	RelationNames      string `json:"relationNames"`      // 关联名称
	BusinessStripNames string `json:"businessStripNames"` // 业务条线名称
}

// PingshuPositionDTO 部门信息DTO
type PingshuPositionDTO struct {
	CreateBy       string `json:"createBy"`       // 创建者ID
	CreateTime     string `json:"createTime"`     // 创建时间
	UpdateBy       string `json:"updateBy"`       // 更新者ID
	UpdateTime     string `json:"updateTime"`     // 更新时间
	ID             string `json:"id"`             // 部门ID
	DeptCode       string `json:"deptCode"`       // 部门编码
	DeptName       string `json:"deptName"`       // 部门名称
	ParentCode     string `json:"parentCode"`     // 上级部门编码
	ParentName     string `json:"parentName"`     // 上级部门名称
	ThirdDeptCode  string `json:"thirdDeptCode"`  // 三级部门编码
	ThirdDeptName  string `json:"thirdDeptName"`  // 三级部门名称
	DisplayOrder   int    `json:"displayOrder"`   // 显示顺序
	Path           string `json:"path"`           // 路径
	Level          int    `json:"level"`          // 层级
	IsRoot         int    `json:"isRoot"`         // 是否是根部门，1是，0否
	Responsibility string `json:"responsibility"` // 责任
	Remark         string `json:"remark"`         // 备注
	Status         int    `json:"status"`         // 状态，1正常，0禁用
	IsDelete       int    `json:"isDelete"`       // 是否删除，0否，1是
	DeptCodes      string `json:"deptCodes"`      // 部门编码列表
	DivisionCode   string `json:"divisionCode"`   // 分区编码
	Leaf           bool   `json:"leaf"`           // 是否是叶子节点，true是，false否
	Department     string `json:"department"`     // 部门全称
	AreaName       string `json:"areaName"`       // 区域名称
	AreaCode       string `json:"areaCode"`       // 区域编码
}

// SaTokenInfo 完整的认证令牌信息
type SaTokenInfo struct {
	TokenName           string `json:"tokenName"`           // 令牌名称
	TokenValue          string `json:"tokenValue"`          // 令牌值
	IsLogin             bool   `json:"isLogin"`             // 是否已登录
	LoginId             string `json:"loginId"`             // 登录ID
	LoginType           string `json:"loginType"`           // 登录类型
	TokenTimeout        int64  `json:"tokenTimeout"`        // 令牌超时时间（秒）
	SessionTimeout      int64  `json:"sessionTimeout"`      // 会话超时时间（秒）
	TokenSessionTimeout int64  `json:"tokenSessionTimeout"` // 令牌会话超时时间（秒）
	TokenActiveTimeout  int64  `json:"tokenActiveTimeout"`  // 令牌活跃超时时间（秒）
	LoginDevice         string `json:"loginDevice"`         // 登录设备信息
	Tag                 string `json:"tag"`                 // 自定义标签
}

// SpiAuthUtil 认证工具类
type SpiAuthUtil struct {
	config        AuthConfig
	tokenName     string
	tokenValue    string
	tokenTimeout  int64
	lastTokenTime int64
	mutex         sync.Mutex
}

// NewSpiAuthUtil 创建认证工具实例
func NewSpiAuthUtil(cfg AuthConfig) *SpiAuthUtil {
	return &SpiAuthUtil{
		config:    cfg,
		tokenName: "Access-Token",
	}
}

// GetTokenStr 获取token值
func (s *SpiAuthUtil) GetTokenStr() string {
	return s.GetSaTokenInfo().TokenValue
}

// GetSaTokenInfo 获取token信息
func (s *SpiAuthUtil) GetSaTokenInfo() *SaTokenInfo {
	s.mutex.Lock()
	defer s.mutex.Unlock()

	currentTime := time.Now().Unix()
	// 检查本地缓存的token是否可用
	if s.tokenValue != "" && (currentTime-s.lastTokenTime) < s.tokenTimeout {
		return &SaTokenInfo{
			TokenName:    s.tokenName,
			TokenValue:   s.tokenValue,
			TokenTimeout: s.tokenTimeout,
		}
	}

	// 缓存不存在或已过期，请求新token
	timestamp := time.Now().UnixMilli()
	str := fmt.Sprintf("appKey=%s&appSecret=%s&timestamp=%d", s.config.AppKey, s.config.AppSecret, timestamp)
	sign := fmt.Sprintf("%x", md5.Sum([]byte(str)))

	jsonData := map[string]interface{}{
		"appKey":    s.config.AppKey,
		"sign":      sign,
		"timestamp": timestamp,
	}

	authUrl := s.buildFullUrl("/app-auth/login")
	resp, err := s.postFormRequest(authUrl, jsonData)
	if err != nil {
		logrus.Errorf("获取token异常: %v", err)
		panic(fmt.Sprintf("获取token异常: %v", err))
	}

	var result struct {
		Code    int         `json:"code"`
		Message string      `json:"message"`
		Data    SaTokenInfo `json:"data"`
	}

	if err := json.Unmarshal(resp, &result); err != nil {
		logrus.Errorf("解析token响应异常: %v", err)
		panic(fmt.Sprintf("解析token响应异常: %v", err))
	}

	if result.Code != 200 {
		logrus.Errorf("获取token失败: %s", result.Message)
		panic(fmt.Sprintf("获取token失败: %s", result.Message))
	}

	// 缓存关键信息
	s.tokenName = result.Data.TokenName
	s.tokenValue = result.Data.TokenValue
	s.tokenTimeout = result.Data.TokenTimeout
	if s.tokenTimeout == 0 {
		s.tokenTimeout = 3600
	}
	s.lastTokenTime = currentTime

	return &result.Data
}

// GetRequest 发送GET请求
func (s *SpiAuthUtil) GetRequest(path string) (string, error) {
	// 确保token有效
	token := s.GetTokenStr()
	// 构建完整URL
	fullUrl := s.buildFullUrl(path)
	// 构建请求
	req, err := http.NewRequest(http.MethodGet, fullUrl, nil)
	if err != nil {
		logrus.Errorf("创建GET请求异常: %v", err)
		return "", fmt.Errorf("创建GET请求异常: %v", err)
	}

	req.Header.Set(s.tokenName, token)
	resp, err := s.doRequest(req)
	if err != nil {
		logrus.Errorf("发送GET请求异常: %v", err)
		return "", fmt.Errorf("发送GET请求异常: %v", err)
	}

	return string(resp), nil
}

// PostRequest 发送POST请求
func (s *SpiAuthUtil) PostRequest(path string, postData interface{}) (string, error) {
	// 确保token有效
	token := s.GetTokenStr()
	// 构建完整URL
	fullUrl := s.buildFullUrl(path)
	// 序列化请求体
	jsonData, err := json.Marshal(postData)
	if err != nil {
		logrus.Errorf("序列化POST请求体异常: %v", err)
		return "", fmt.Errorf("序列化POST请求体异常: %v", err)
	}

	// 构建请求
	req, err := http.NewRequest(http.MethodPost, fullUrl, bytes.NewBuffer(jsonData))
	if err != nil {
		logrus.Errorf("创建POST请求异常: %v", err)
		return "", fmt.Errorf("创建POST请求异常: %v", err)
	}

	req.Header.Set("Content-Type", "application/json")
	req.Header.Set(s.tokenName, token)

	resp, err := s.doRequest(req)
	if err != nil {
		logrus.Errorf("发送POST请求异常: %v", err)
		return "", fmt.Errorf("发送POST请求异常: %v", err)
	}

	return string(resp), nil
}

// DeleteRequest 发送DELETE请求
func (s *SpiAuthUtil) DeleteRequest(path string, body interface{}) (string, error) {
	// 确保token有效
	token := s.GetTokenStr()
	// 构建完整URL
	fullUrl := s.buildFullUrl(path)
	// 序列化请求体
	jsonData, err := json.Marshal(body)
	if err != nil {
		logrus.Errorf("序列化DELETE请求体异常: %v", err)
		return "", fmt.Errorf("序列化DELETE请求体异常: %v", err)
	}

	// 构建请求
	req, err := http.NewRequest(http.MethodDelete, fullUrl, bytes.NewBuffer(jsonData))
	if err != nil {
		logrus.Errorf("创建DELETE请求异常: %v", err)
		return "", fmt.Errorf("创建DELETE请求异常: %v", err)
	}

	req.Header.Set("Content-Type", "application/json")
	req.Header.Set(s.tokenName, token)

	resp, err := s.doRequest(req)
	if err != nil {
		logrus.Errorf("发送DELETE请求异常: %v", err)
		return "", fmt.Errorf("发送DELETE请求异常: %v", err)
	}

	return string(resp), nil
}

// buildFullUrl 构建完整URL
func (s *SpiAuthUtil) buildFullUrl(path string) string {
	return s.config.BaseURL + path
}

// postFormRequest 发送表单POST请求
func (s *SpiAuthUtil) postFormRequest(url string, data map[string]interface{}) ([]byte, error) {
	// 构建表单数据
	formData := make([]string, 0, len(data))
	for key, value := range data {
		formData = append(formData, fmt.Sprintf("%s=%v", key, value))
	}
	formBody := strings.Join(formData, "&")

	// 创建请求
	req, err := http.NewRequest(http.MethodPost, url, strings.NewReader(formBody))
	if err != nil {
		return nil, err
	}

	req.Header.Set("Content-Type", "application/x-www-form-urlencoded")

	// 发送请求
	resp, err := s.doRequest(req)
	if err != nil {
		return nil, err
	}

	return resp, nil
}

// doRequest 执行HTTP请求
func (s *SpiAuthUtil) doRequest(req *http.Request) ([]byte, error) {
	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	body, err := io.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}

	return body, nil
}

// CheckSsoAuth 登录状态校验 (SSO 认证中心重定向)
func (s *SpiAuthUtil) CheckSsoAuth() (string, error) {
	authUrl := s.config.BaseAuthURL + SSO_AUTH_PATH +
		"?client_id=" + s.config.AppID +
		"&redirect=" + s.config.RedirectURI

	return authUrl, nil
}

// CheckTicket 根据 ticket 获取 token
func (s *SpiAuthUtil) CheckTicket(ticket string) (string, error) {
	// 构建完整URL，带上查询参数
	pathWithParams := fmt.Sprintf("%s?client_id=%s&ticket=%s&ssoLogoutCall=%s",
		SSO_CHECK_TICKET_PATH, s.config.AppID, ticket, s.config.LogoutCallbackURI)
	fullUrl := s.buildFullUrl(pathWithParams)

	// 构建请求
	req, err := http.NewRequest(http.MethodGet, fullUrl, nil)
	if err != nil {
		logrus.Errorf("创建checkTicket请求异常: %v", err)
		return "", fmt.Errorf("创建checkTicket请求异常: %v", err)
	}

	// checkTicket接口不需要传token
	resp, err := s.doRequest(req)
	if err != nil {
		logrus.Errorf("发送checkTicket请求异常: %v", err)
		return "", fmt.Errorf("发送checkTicket请求异常: %v", err)
	}

	logrus.Infof("根据ticket获取token响应: %s", string(resp))
	return string(resp), nil
}

// GetUserInfo 根据 token 获取用户信息
func (s *SpiAuthUtil) GetUserInfo(accessToken string) (string, error) {
	token := s.GetTokenStr()
	pathWithParams := fmt.Sprintf("%s?accessToken=%s", SSO_USERINFO_PATH, accessToken)
	fullUrl := s.buildFullUrl(pathWithParams)

	// 构建请求
	req, err := http.NewRequest(http.MethodGet, fullUrl, nil)
	if err != nil {
		logrus.Errorf("创建getUserInfo请求异常: %v", err)
		return "", fmt.Errorf("创建getUserInfo请求异常: %v", err)
	}

	req.Header.Set(s.tokenName, token)
	resp, err := s.doRequest(req)
	if err != nil {
		logrus.Errorf("发送getUserInfo请求异常: %v", err)
		return "", fmt.Errorf("发送getUserInfo请求异常: %v", err)
	}

	logrus.Infof("获取用户信息响应: %s", string(resp))
	return string(resp), nil
}

// SignOut 单点注销
func (s *SpiAuthUtil) SignOut(loginId string) (string, error) {
	// 确保token有效
	token := s.GetTokenStr()
	// 构建完整URL，带上查询参数
	pathWithParams := fmt.Sprintf("%s?loginId=%s", SSO_SIGNOUT_PATH, loginId)
	fullUrl := s.buildFullUrl(pathWithParams)

	// 构建请求
	req, err := http.NewRequest(http.MethodGet, fullUrl, nil)
	if err != nil {
		logrus.Errorf("创建signOut请求异常: %v", err)
		return "", fmt.Errorf("创建signOut请求异常: %v", err)
	}

	req.Header.Set(s.tokenName, token)
	resp, err := s.doRequest(req)
	if err != nil {
		logrus.Errorf("发送signOut请求异常: %v", err)
		return "", fmt.Errorf("发送signOut请求异常: %v", err)
	}

	logrus.Infof("单点注销响应: %s", string(resp))
	return string(resp), nil
}

// SpiService 认证服务SPI接口
type SpiService struct {
	authUtil *SpiAuthUtil
}

// NewSpiService 创建SpiService实例
func NewSpiService(authUtil *SpiAuthUtil) *SpiService {
	return &SpiService{
		authUtil: authUtil,
	}
}

// 默认分页参数
const (
	DEFAULT_PAGE_NUM  = "1"
	DEFAULT_PAGE_SIZE = "10"
	SYNC_PAGE_SIZE    = 999
)

// 同步相关常量
const (
	ROOT_ORG_NAME    = "平湖市交通运输局"
	ROOT_PARENT_CODE = "GO_ade3bc713fc146f0aa6620c1b8d22312"
)

// SSO相关常量
const (
	SSO_AUTH_PATH         = "/sso/auth"        // 登录状态校验路径
	SSO_CHECK_TICKET_PATH = "/sso/checkTicket" // 根据ticket获取token路径
	SSO_USERINFO_PATH     = "/sso/userinfo"    // 根据token获取用户信息路径
	SSO_SIGNOUT_PATH      = "/sso/signout"     // 单点注销路径
)

// 同步状态
type SyncStatus struct {
	IsRunning    bool      `json:"isRunning"`
	LastSyncTime time.Time `json:"lastSyncTime"`
	TotalUsers   int       `json:"totalUsers"`
	TotalDepts   int       `json:"totalDepts"`
	ErrorMsg     string    `json:"errorMsg,omitempty"`
}

// 全局同步状态
var globalSyncStatus = &SyncStatus{
	IsRunning: false,
}

// 同步状态互斥锁
var syncMutex sync.Mutex

// GetTokenStr 获取当前登录用户的Token字符串
func (s *SpiService) GetTokenStr() string {
	return s.authUtil.GetTokenStr()
}

// HandlePageParam 处理分页参数
func (s *SpiService) HandlePageParam(params map[string]interface{}) map[string]interface{} {
	if params == nil {
		params = make(map[string]interface{})
	}
	if _, ok := params["pageNum"]; !ok || params["pageNum"] == nil {
		params["pageNum"] = DEFAULT_PAGE_NUM
	}
	if _, ok := params["pageSize"]; !ok || params["pageSize"] == nil {
		params["pageSize"] = DEFAULT_PAGE_SIZE
	}
	return params
}

// GetUserList 获取用户列表
func (s *SpiService) GetUserList(params map[string]interface{}) (string, error) {
	pageMap := s.HandlePageParam(params)
	// 拼接query字符串
	const USER_LIST_URL = "/spi/user/page"
	var sb strings.Builder
	sb.WriteString(USER_LIST_URL)
	if len(pageMap) > 0 {
		sb.WriteString("?")
		for key, value := range pageMap {
			if value != nil {
				sb.WriteString(fmt.Sprintf("%s=%v&", key, value))
			} else {
				sb.WriteString(fmt.Sprintf("%s=&", key))
			}
		}
		// 去掉最后一个&
		str := sb.String()
		str = str[:len(str)-1]
		return s.authUtil.GetRequest(str)
	}
	return s.authUtil.GetRequest(USER_LIST_URL)
}

// GetUserDetail 获取用户详情
func (s *SpiService) GetUserDetail(params map[string]interface{}) (string, error) {
	// 校验必填参数 userId
	if params == nil || params["userId"] == nil {
		return "", fmt.Errorf("userId 参数不能为空")
	}
	// 拼接query字符串
	var sb strings.Builder
	sb.WriteString("/spi/user/details?")
	for key, value := range params {
		if value != nil {
			sb.WriteString(fmt.Sprintf("%s=%v&", key, value))
		} else {
			sb.WriteString(fmt.Sprintf("%s=&", key))
		}
	}
	// 去掉最后一个&
	str := sb.String()
	str = str[:len(str)-1]
	return s.authUtil.GetRequest(str)
}

// GetUserDeptList 获取用户绑定的部门列表
func (s *SpiService) GetUserDeptList(params map[string]interface{}) (string, error) {
	// 校验必填参数 userId
	if params == nil || params["userId"] == nil {
		return "", fmt.Errorf("userId 参数不能为空")
	}
	// 拼接query字符串
	var sb strings.Builder
	sb.WriteString("/spi/user/deptList?")
	for key, value := range params {
		if value != nil {
			sb.WriteString(fmt.Sprintf("%s=%v&", key, value))
		} else {
			sb.WriteString(fmt.Sprintf("%s=&", key))
		}
	}
	// 去掉最后一个&
	str := sb.String()
	str = str[:len(str)-1]
	return s.authUtil.GetRequest(str)
}

// GetDeptList 获取部门列表
func (s *SpiService) GetDeptList(params map[string]interface{}) (string, error) {
	pageMap := s.HandlePageParam(params)
	// 拼接query字符串
	const DEPT_LIST_URL = "/spi/dept/list"
	var sb strings.Builder
	sb.WriteString(DEPT_LIST_URL)
	if len(pageMap) > 0 {
		sb.WriteString("?")
		for key, value := range pageMap {
			if value != nil {
				sb.WriteString(fmt.Sprintf("%s=%v&", key, value))
			} else {
				sb.WriteString(fmt.Sprintf("%s=&", key))
			}
		}
		// 去掉最后一个&
		str := sb.String()
		str = str[:len(str)-1]
		return s.authUtil.GetRequest(str)
	}
	return s.authUtil.GetRequest(DEPT_LIST_URL)
}

// convertToNumericKey 将字符串转换为数字键
func convertToNumericKey(input string) int64 {
	hash := sha256.Sum256([]byte(input))
	var numericKey int64
	for i := 0; i < 8; i++ {
		numericKey = (numericKey << 8) | int64(hash[i]&0xFF)
	}
	if numericKey < 0 {
		numericKey = -numericKey
	}
	return numericKey
}

// SyncService 同步服务
type SyncService struct {
	spiService *SpiService
}

// NewSyncService 创建同步服务实例
func NewSyncService(spiService *SpiService) *SyncService {
	return &SyncService{
		spiService: spiService,
	}
}

// SyncUsers 同步用户数据
func (s *SyncService) SyncUsers() error {
	syncMutex.Lock()
	defer syncMutex.Unlock()

	if globalSyncStatus.IsRunning {
		return fmt.Errorf("同步正在进行中，请稍后再试")
	}

	globalSyncStatus.IsRunning = true
	globalSyncStatus.ErrorMsg = ""

	defer func() {
		globalSyncStatus.IsRunning = false
		globalSyncStatus.LastSyncTime = time.Now()
	}()

	logrus.Info("开始同步用户数据...")

	// 分页拉取用户数据
	pageNum := 1
	pageSize := SYNC_PAGE_SIZE
	var allUsers []PingshuUserDTO

	for {
		params := map[string]interface{}{
			"pageNum":  strconv.Itoa(pageNum),
			"pageSize": strconv.Itoa(pageSize),
		}

		response, err := s.spiService.GetUserList(params)
		if err != nil {
			globalSyncStatus.ErrorMsg = fmt.Sprintf("获取用户列表失败: %v", err)
			return fmt.Errorf("获取用户列表失败: %v", err)
		}

		var result struct {
			Code    int    `json:"code"`
			Message string `json:"message"`
			Data    struct {
				List []PingshuUserDTO `json:"list"`
			} `json:"data"`
		}

		if err := json.Unmarshal([]byte(response), &result); err != nil {
			globalSyncStatus.ErrorMsg = fmt.Sprintf("解析用户列表响应失败: %v", err)
			return fmt.Errorf("解析用户列表响应失败: %v", err)
		}

		if result.Code != 200 {
			globalSyncStatus.ErrorMsg = fmt.Sprintf("获取用户列表失败: %s", result.Message)
			return fmt.Errorf("获取用户列表失败: %s", result.Message)
		}

		if len(result.Data.List) == 0 {
			break
		}

		// 过滤出平湖市交通运输局的用户
		for _, user := range result.Data.List {
			for _, position := range user.Positions {
				if position.ThirdDeptName == ROOT_ORG_NAME {
					allUsers = append(allUsers, user)
					break
				}
			}
		}

		logrus.Infof("第 %d 页拉取完成，记录数: %d", pageNum, len(result.Data.List))

		if len(result.Data.List) < pageSize {
			break
		}

		pageNum++
	}

	globalSyncStatus.TotalUsers = len(allUsers)
	logrus.Infof("用户数据拉取完成，总用户数: %d", len(allUsers))

	// 这里可以添加将用户数据保存到数据库的逻辑
	// 目前只是模拟同步完成
	logrus.Info("用户数据同步完成")

	return nil
}

// SyncDepartments 同步部门数据
func (s *SyncService) SyncDepartments() error {
	syncMutex.Lock()
	defer syncMutex.Unlock()

	if globalSyncStatus.IsRunning {
		return fmt.Errorf("同步正在进行中，请稍后再试")
	}

	globalSyncStatus.IsRunning = true
	globalSyncStatus.ErrorMsg = ""

	defer func() {
		globalSyncStatus.IsRunning = false
		globalSyncStatus.LastSyncTime = time.Now()
	}()

	logrus.Info("开始同步部门数据...")

	// 分页拉取部门数据
	pageNum := 1
	pageSize := SYNC_PAGE_SIZE
	var allDepts []PingshuPositionDTO

	for {
		params := map[string]interface{}{
			"pageNum":  strconv.Itoa(pageNum),
			"pageSize": strconv.Itoa(pageSize),
		}

		response, err := s.spiService.GetDeptList(params)
		if err != nil {
			globalSyncStatus.ErrorMsg = fmt.Sprintf("获取部门列表失败: %v", err)
			return fmt.Errorf("获取部门列表失败: %v", err)
		}

		var result struct {
			Code    int                  `json:"code"`
			Message string               `json:"message"`
			Data    []PingshuPositionDTO `json:"data"`
		}

		if err := json.Unmarshal([]byte(response), &result); err != nil {
			globalSyncStatus.ErrorMsg = fmt.Sprintf("解析部门列表响应失败: %v", err)
			return fmt.Errorf("解析部门列表响应失败: %v", err)
		}

		if result.Code != 200 {
			globalSyncStatus.ErrorMsg = fmt.Sprintf("获取部门列表失败: %s", result.Message)
			return fmt.Errorf("获取部门列表失败: %s", result.Message)
		}

		if len(result.Data) == 0 {
			break
		}

		allDepts = append(allDepts, result.Data...)

		logrus.Infof("第 %d 页拉取完成，记录数: %d", pageNum, len(result.Data))

		if len(result.Data) < pageSize {
			break
		}

		pageNum++
	}

	// 过滤出平湖市交通运输局及其子部门
	var filteredDepts []PingshuPositionDTO
	parentMap := make(map[string][]PingshuPositionDTO)
	deptCodeMap := make(map[string]PingshuPositionDTO)

	// 构建映射关系
	for _, dept := range allDepts {
		if dept.ParentCode != "" {
			parentMap[dept.ParentCode] = append(parentMap[dept.ParentCode], dept)
		}
		deptCodeMap[dept.DeptCode] = dept
	}

	// 递归收集指定父部门下的所有子部门
	visited := make(map[string]bool)
	s.collectDepartmentsRecursive(ROOT_PARENT_CODE, parentMap, &filteredDepts, visited)

	globalSyncStatus.TotalDepts = len(filteredDepts)
	logrus.Infof("部门数据拉取完成，总部门数: %d", len(filteredDepts))
	for _, dept := range filteredDepts {
		fmt.Println("DeptName:", dept.DeptName)
	}
	// 这里可以添加将部门数据保存到数据库的逻辑
	// 目前只是模拟同步完成
	logrus.Info("部门数据同步完成")

	return nil
}

// collectDepartmentsRecursive 递归收集部门
func (s *SyncService) collectDepartmentsRecursive(parentCode string, parentMap map[string][]PingshuPositionDTO, result *[]PingshuPositionDTO, visited map[string]bool) {
	children := parentMap[parentCode]
	if children == nil {
		return
	}

	for _, child := range children {
		if visited[child.DeptCode] {
			continue
		}
		*result = append(*result, child)
		visited[child.DeptCode] = true
		s.collectDepartmentsRecursive(child.DeptCode, parentMap, result, visited)
	}
}

// SyncAll 同步所有数据
func (s *SyncService) SyncAll() error {
	logrus.Info("开始同步所有数据...")

	// 先同步部门
	if err := s.SyncDepartments(); err != nil {
		return fmt.Errorf("同步部门失败: %v", err)
	}

	// 再同步用户
	if err := s.SyncUsers(); err != nil {
		return fmt.Errorf("同步用户失败: %v", err)
	}

	logrus.Info("所有数据同步完成")
	return nil
}

// GetSyncStatus 获取同步状态
func GetSyncStatus() SyncStatus {
	syncMutex.Lock()
	defer syncMutex.Unlock()
	return *globalSyncStatus
}

// 初始化配置和服务
var (
	authConfig  AuthConfig
	authUtil    *SpiAuthUtil
	spiService  *SpiService
	syncService *SyncService
)

func init() {
	// 配置参数
	authConfig = AuthConfig{
		BaseURL:           "http://36.26.49.34:30188", // 请替换为实际的API地址
		BaseAuthURL:       "http://36.26.49.34:30187", // 统一登录跳转URL
		AppID:             "1935172028808638464",      // 应用ID
		AppKey:            "e484e357790f4ae987f15bbc5fe781ba",
		AppSecret:         "20870da4ba654ae49d6e7cc6a87ae0f4",
		RedirectURI:       "http://localhost:8080/sso/callback", // 重定向URI
		LogoutCallbackURI: "http://localhost:8080/sso/logout",   // 登出回调URI
	}

	// 创建服务实例
	authUtil = NewSpiAuthUtil(authConfig)
	spiService = NewSpiService(authUtil)
	syncService = NewSyncService(spiService)
}

func main() {
	// 设置gin模式
	gin.SetMode(gin.ReleaseMode)

	// 创建gin引擎
	r := gin.Default()

	// 添加CORS中间件
	r.Use(func(c *gin.Context) {
		c.Header("Access-Control-Allow-Origin", "*")
		c.Header("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS")
		c.Header("Access-Control-Allow-Headers", "Origin, Content-Type, Accept, Authorization, X-Requested-With")

		if c.Request.Method == "OPTIONS" {
			c.AbortWithStatus(204)
			return
		}

		c.Next()
	})

	// API路由组
	api := r.Group("/api/v1")
	{
		// 同步相关接口
		sync := api.Group("/sync")
		{
			sync.POST("/users", syncUsersHandler)
			sync.POST("/departments", syncDepartmentsHandler)
			sync.POST("/all", syncAllHandler)
			sync.GET("/status", getSyncStatusHandler)
		}

		// SPI相关接口
		spi := api.Group("/spi")
		{
			spi.GET("/token", getTokenHandler)
			spi.GET("/users", getUsersHandler)
			spi.GET("/users/:userId", getUserDetailHandler)
			spi.GET("/users/:userId/depts", getUserDeptsHandler)
			spi.GET("/departments", getDepartmentsHandler)
		}

	}

	// SSO相关接口
	sso := r.Group("/sso")
	{
		sso.GET("/auth", ssoAuthHandler)             // 方式1: 跳转到中枢登录页面
		sso.GET("/callback", ssoCallbackHandler)     // 方式1: 回调处理
		sso.POST("/checkTicket", checkTicketHandler) // 方式1: 根据ticket获取token
		sso.GET("/userinfo", getUserInfoHandler)     // 方式2: 根据token获取用户信息
		sso.POST("/logout", signOutHandler)          // 单点注销
	}

	// Dashboard接口
	r.GET("/dashboard", dashboardHandler)
	// 健康检查接口
	r.GET("/health", func(c *gin.Context) {
		c.JSON(200, gin.H{
			"status": "ok",
			"time":   time.Now().Format("2006-01-02 15:04:05"),
		})
	})

	// 测试token获取接口
	r.GET("/test/token", func(c *gin.Context) {
		tokenInfo := authUtil.GetSaTokenInfo()
		c.JSON(200, gin.H{
			"code":    200,
			"message": "Token获取成功",
			"data": gin.H{
				"tokenName":    tokenInfo.TokenName,
				"tokenValue":   tokenInfo.TokenValue,
				"tokenTimeout": tokenInfo.TokenTimeout,
			},
		})
	})

	// 启动服务器
	logrus.Info("服务器启动在端口 8080")
	if err := r.Run(":8080"); err != nil {
		logrus.Fatalf("服务器启动失败: %v", err)
	}
}

// 同步用户处理器
func syncUsersHandler(c *gin.Context) {
	if err := syncService.SyncUsers(); err != nil {
		c.JSON(500, gin.H{
			"code":    500,
			"message": err.Error(),
		})
		return
	}

	c.JSON(200, gin.H{
		"code":    200,
		"message": "用户同步完成",
		"data":    GetSyncStatus(),
	})
}

// 同步部门处理器
func syncDepartmentsHandler(c *gin.Context) {
	if err := syncService.SyncDepartments(); err != nil {
		c.JSON(500, gin.H{
			"code":    500,
			"message": err.Error(),
		})
		return
	}

	c.JSON(200, gin.H{
		"code":    200,
		"message": "部门同步完成",
		"data":    GetSyncStatus(),
	})
}

// 同步所有数据处理器
func syncAllHandler(c *gin.Context) {
	if err := syncService.SyncAll(); err != nil {
		c.JSON(500, gin.H{
			"code":    500,
			"message": err.Error(),
		})
		return
	}

	c.JSON(200, gin.H{
		"code":    200,
		"message": "所有数据同步完成",
		"data":    GetSyncStatus(),
	})
}

// 获取同步状态处理器
func getSyncStatusHandler(c *gin.Context) {
	c.JSON(200, gin.H{
		"code":    200,
		"message": "获取同步状态成功",
		"data":    GetSyncStatus(),
	})
}

// 获取token处理器
func getTokenHandler(c *gin.Context) {
	token := spiService.GetTokenStr()
	c.JSON(200, gin.H{
		"code":    200,
		"message": "获取token成功",
		"data": gin.H{
			"token": token,
		},
	})
}

// 获取用户列表处理器
func getUsersHandler(c *gin.Context) {
	pageNum := c.DefaultQuery("pageNum", "1")
	pageSize := c.DefaultQuery("pageSize", "10")

	params := map[string]interface{}{
		"pageNum":  pageNum,
		"pageSize": pageSize,
	}

	response, err := spiService.GetUserList(params)
	if err != nil {
		c.JSON(500, gin.H{
			"code":    500,
			"message": err.Error(),
		})
		return
	}

	var result map[string]interface{}
	if err := json.Unmarshal([]byte(response), &result); err != nil {
		c.JSON(500, gin.H{
			"code":    500,
			"message": "解析响应失败",
		})
		return
	}

	c.JSON(200, result)
}

// 获取用户详情处理器
func getUserDetailHandler(c *gin.Context) {
	userId := c.Param("userId")
	if userId == "" {
		c.JSON(400, gin.H{
			"code":    400,
			"message": "用户ID不能为空",
		})
		return
	}

	params := map[string]interface{}{
		"userId": userId,
	}

	response, err := spiService.GetUserDetail(params)
	if err != nil {
		c.JSON(500, gin.H{
			"code":    500,
			"message": err.Error(),
		})
		return
	}

	var result map[string]interface{}
	if err := json.Unmarshal([]byte(response), &result); err != nil {
		c.JSON(500, gin.H{
			"code":    500,
			"message": "解析响应失败",
		})
		return
	}

	c.JSON(200, result)
}

// 获取用户部门列表处理器
func getUserDeptsHandler(c *gin.Context) {
	userId := c.Param("userId")
	if userId == "" {
		c.JSON(400, gin.H{
			"code":    400,
			"message": "用户ID不能为空",
		})
		return
	}

	params := map[string]interface{}{
		"userId": userId,
	}

	response, err := spiService.GetUserDeptList(params)
	if err != nil {
		c.JSON(500, gin.H{
			"code":    500,
			"message": err.Error(),
		})
		return
	}

	var result map[string]interface{}
	if err := json.Unmarshal([]byte(response), &result); err != nil {
		c.JSON(500, gin.H{
			"code":    500,
			"message": "解析响应失败",
		})
		return
	}

	c.JSON(200, result)
}

// 获取部门列表处理器
func getDepartmentsHandler(c *gin.Context) {
	pageNum := c.DefaultQuery("pageNum", "1")
	pageSize := c.DefaultQuery("pageSize", "10")

	params := map[string]interface{}{
		"pageNum":  pageNum,
		"pageSize": pageSize,
	}

	response, err := spiService.GetDeptList(params)
	if err != nil {
		c.JSON(500, gin.H{
			"code":    500,
			"message": err.Error(),
		})
		return
	}

	var result map[string]interface{}
	if err := json.Unmarshal([]byte(response), &result); err != nil {
		c.JSON(500, gin.H{
			"code":    500,
			"message": "解析响应失败",
		})
		return
	}

	c.JSON(200, result)
}

// SSO认证处理器 - 方式1: 跳转到中枢登录页面
func ssoAuthHandler(c *gin.Context) {
	authUrl, err := authUtil.CheckSsoAuth()
	if err != nil {
		c.JSON(500, gin.H{
			"code":    500,
			"message": "生成认证URL失败",
			"error":   err.Error(),
		})
		return
	}

	// 返回跳转信息
	c.JSON(302, gin.H{
		"code":    302,
		"message": "需要跳转",
		"url":     authUrl,
	})
}

// SSO回调处理器 - 方式1: 处理中枢登录后的回调
func ssoCallbackHandler(c *gin.Context) {
	ticket := c.Query("ticket")
	if ticket == "" {
		c.JSON(400, gin.H{
			"code":    400,
			"message": "缺少ticket参数",
		})
		return
	}

	// 根据ticket获取token
	response, err := authUtil.CheckTicket(ticket)
	if err != nil {
		c.JSON(500, gin.H{
			"code":    500,
			"message": "根据ticket获取token失败",
			"error":   err.Error(),
		})
		return
	}

	var result map[string]interface{}
	if err := json.Unmarshal([]byte(response), &result); err != nil {
		c.JSON(500, gin.H{
			"code":    500,
			"message": "解析响应失败",
			"error":   err.Error(),
		})
		return
	}

	// 如果成功获取到token，可以在这里实现自动登录逻辑
	// 例如：生成自己系统的session或jwt token
	if code, ok := result["code"].(float64); ok && code == 200 {
		// 这里可以添加自动登录逻辑
		logrus.Info("SSO登录成功，ticket:", ticket)

		// 从响应中提取token
		if data, ok := result["data"].(map[string]interface{}); ok {
			if accessToken, ok := data["accessToken"].(string); ok {
				logrus.Infof("成功获取到token: %s", accessToken)
				// 重定向到dashboard页面，带上ticket和token参数
				c.Redirect(302, "/dashboard?ticket="+ticket+"&token="+accessToken)
				return
			}
		}
	}

	c.JSON(200, result)
}

// 检查ticket处理器
func checkTicketHandler(c *gin.Context) {
	var request struct {
		Ticket string `json:"ticket" binding:"required"`
	}

	if err := c.ShouldBindJSON(&request); err != nil {
		c.JSON(400, gin.H{
			"code":    400,
			"message": "请求参数错误",
			"error":   err.Error(),
		})
		return
	}

	response, err := authUtil.CheckTicket(request.Ticket)
	if err != nil {
		c.JSON(500, gin.H{
			"code":    500,
			"message": "根据ticket获取token失败",
			"error":   err.Error(),
		})
		return
	}

	var result map[string]interface{}
	if err := json.Unmarshal([]byte(response), &result); err != nil {
		c.JSON(500, gin.H{
			"code":    500,
			"message": "解析响应失败",
			"error":   err.Error(),
		})
		return
	}

	// 如果成功获取到token，打印token并跳转到dashboard
	if code, ok := result["code"].(float64); ok && code == 200 {
		if data, ok := result["data"].(map[string]interface{}); ok {
			if token, ok := data["accessToken"].(string); ok {
				logrus.Infof("成功获取到token: %s", token)
				// 跳转到dashboard页面
				c.Redirect(302, "/dashboard?ticket="+request.Ticket+"&token="+token)
				return
			}
		}
	}

	c.JSON(200, result)
}

// Dashboard处理器 - 显示ticket、token及用户信息
func dashboardHandler(c *gin.Context) {
	ticket := c.Query("ticket")
	token := c.Query("token")

	if ticket == "" || token == "" {
		c.JSON(400, gin.H{
			"code":    400,
			"message": "缺少ticket或token参数",
		})
		return
	}

	// 根据token获取用户信息
	userInfoResponse, err := authUtil.GetUserInfo(token)
	if err != nil {
		c.JSON(500, gin.H{
			"code":    500,
			"message": "获取用户信息失败",
			"error":   err.Error(),
		})
		return
	}

	var userInfoResult map[string]interface{}
	if err := json.Unmarshal([]byte(userInfoResponse), &userInfoResult); err != nil {
		c.JSON(500, gin.H{
			"code":    500,
			"message": "解析用户信息响应失败",
			"error":   err.Error(),
		})
		return
	}

	// 构建dashboard响应数据
	dashboardData := gin.H{
		"ticket":    ticket,
		"token":     token,
		"userInfo":  userInfoResult,
		"timestamp": time.Now().Format("2006-01-02 15:04:05"),
	}

	// 如果用户信息获取成功，记录日志
	if code, ok := userInfoResult["code"].(float64); ok && code == 200 {
		logrus.Infof("Dashboard访问成功 - Ticket: %s, Token: %s", ticket, token)
	}

	c.JSON(200, gin.H{
		"code":    200,
		"message": "Dashboard数据获取成功",
		"data":    dashboardData,
	})
}

// 获取用户信息处理器 - 方式2: 根据token获取用户信息实现免登录
func getUserInfoHandler(c *gin.Context) {
	accessToken := c.Query("accessToken")
	if accessToken == "" {
		c.JSON(400, gin.H{
			"code":    400,
			"message": "缺少accessToken参数",
		})
		return
	}

	response, err := authUtil.GetUserInfo(accessToken)
	if err != nil {
		c.JSON(500, gin.H{
			"code":    500,
			"message": "获取用户信息失败",
			"error":   err.Error(),
		})
		return
	}

	var result map[string]interface{}
	if err := json.Unmarshal([]byte(response), &result); err != nil {
		c.JSON(500, gin.H{
			"code":    500,
			"message": "解析响应失败",
			"error":   err.Error(),
		})
		return
	}

	// 如果成功获取到用户信息，可以在这里实现免登录逻辑
	// 例如：验证用户是否存在于本地系统，如果存在则自动登录
	if code, ok := result["code"].(float64); ok && code == 200 {
		logrus.Info("获取用户信息成功，accessToken:", accessToken)

		// 这里可以添加免登录逻辑
		// 例如：根据用户信息查找本地用户，生成session等
	}

	c.JSON(200, result)
}

// 单点注销处理器
func signOutHandler(c *gin.Context) {
	var request struct {
		LoginId string `json:"loginId" binding:"required"`
	}

	if err := c.ShouldBindJSON(&request); err != nil {
		c.JSON(400, gin.H{
			"code":    400,
			"message": "请求参数错误",
			"error":   err.Error(),
		})
		return
	}

	response, err := authUtil.SignOut(request.LoginId)
	if err != nil {
		c.JSON(500, gin.H{
			"code":    500,
			"message": "单点注销失败",
			"error":   err.Error(),
		})
		return
	}

	var result map[string]interface{}
	if err := json.Unmarshal([]byte(response), &result); err != nil {
		c.JSON(500, gin.H{
			"code":    500,
			"message": "解析响应失败",
			"error":   err.Error(),
		})
		return
	}

	c.JSON(200, result)
}
